import Message from './Message.svelte';
import { mount, unmount } from 'svelte';
import type { MessageOptions, MessagePosition } from './types';

interface InternalInst {
	id: string;
	component: ReturnType<typeof mount>; // 真正的组件实例
}

/* ---- 队列 ---- */
const queue: Record<MessagePosition, InternalInst[]> = {
	top: [],
	'top-left': [],
	'top-right': [],
	bottom: [],
	'bottom-left': [],
	'bottom-right': []
};

const CFG = { height: 40, gap: 14, base: 14 };
let seed = 0;

/* ---- 基础 open ---- */
function open(opts: MessageOptions) {
	const id = `${Date.now()}_${++seed}`;
	const {
		message,
		type = 'primary',
		duration = 2000,
		showClose = false,
		position = 'top',
		onClose
	} = opts;

	if (!message.trim()) throw new Error('[Message] message is required');

	const q = queue[position];
	const index = q.length;	
	const offset = CFG.base + index * (CFG.height + CFG.gap);

	const component = mount(Message, {
		target: document.body,
		props: {
			id,
			type,
			message,
			duration,
			showClose,
			position,
			index,
			offset,
			onClose: () => {
				remove(position, id);
				onClose?.();
			}
		}
	});

	q.push({ id, component });
	return { close: () => remove(position, id) };
}

/* ---- 关闭 & 队列整理 ---- */
function remove(pos: MessagePosition, id: string) {
	const q = queue[pos];
	const idx = q.findIndex((v) => v.id === id);
	if (idx === -1) return;

	unmount(q[idx].component); // ← 官方卸载方式
	q.splice(idx, 1);

	// 重排后续消息
	q.forEach((v, i) => {
		const offset = CFG.base + i * (CFG.height + CFG.gap);
		const el = document.querySelector(`[data-id="${v.id}"]`) as HTMLElement;
		if (el) {
			if (pos.startsWith('top')) el.style.top = `${offset}px`;
			else el.style.bottom = `${offset}px`;
		}
	});
}

/* ---- 快捷方法 ---- */
export const MessageApi = {
	open,
	success: (msg: string | Omit<MessageOptions, 'type'>) =>
		typeof msg === 'string'
			? open({ message: msg, type: 'success' })
			: open({ ...msg, type: 'success' }),
	warning: (msg: string | Omit<MessageOptions, 'type'>) =>
		typeof msg === 'string'
			? open({ message: msg, type: 'warning' })
			: open({ ...msg, type: 'warning' }),
	info: (msg: string | Omit<MessageOptions, 'type'>) =>
		typeof msg === 'string' ? open({ message: msg, type: 'info' }) : open({ ...msg, type: 'info' }),
	error: (msg: string | Omit<MessageOptions, 'type'>) =>
		typeof msg === 'string'
			? open({ message: msg, type: 'error' })
			: open({ ...msg, type: 'error' }),
	primary: (msg: string | Omit<MessageOptions, 'type'>) =>
		typeof msg === 'string'
			? open({ message: msg, type: 'primary' })
			: open({ ...msg, type: 'primary' }),

	clear: (pos?: MessagePosition) => {
		if (pos) {
			queue[pos].forEach((v) => unmount(v.component));
			queue[pos] = [];
		} else {
			Object.values(queue).forEach((q) => q.forEach((v) => unmount(v.component)));
			Object.keys(queue).forEach((k) => (queue[k as MessagePosition] = []));
		}
	}
};

export default MessageApi;
